# -*- coding: utf-8 -*-
"""
Python 企业级类和对象最佳实践示例

本模块演示了Python面向对象编程的企业级最佳实践，包括:
- 数据类和类型注解
- 属性装饰器和描述符
- 魔术方法和运算符重载
- 继承和多态最佳实践
- 抽象基类和接口设计
- 单例模式和工厂模式
- 上下文管理器类
"""

import logging
from abc import ABC, abstractmethod
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum, auto
from functools import total_ordering
from typing import Any, ClassVar, Dict, List, Optional, Protocol, Union
from weakref import WeakSet
import threading

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(levelname)s:%(name)s:%(message)s'
)
logger = logging.getLogger(__name__)

class AnimalType(Enum):
    """动物类型枚举"""
    DOG = auto()
    CAT = auto()
    BIRD = auto()

class Validatable(Protocol):
    """可验证协议"""
    def validate(self) -> bool:
        """验证对象状态"""
        ...

@dataclass
class AnimalInfo:
    """动物信息数据类"""
    name: str
    age: int
    breed: str
    weight: float = 0.0
    vaccinated: bool = False
    tags: List[str] = field(default_factory=list)
    metadata: Dict[str, Any] = field(default_factory=dict)
    
    def __post_init__(self):
        """数据类后处理"""
        if self.age < 0:
            raise ValueError("年龄不能为负数")
        if self.weight < 0:
            raise ValueError("体重不能为负数")
        
        # 自动添加创建时间
        self.metadata.setdefault('created_at', datetime.now().isoformat())

class TemperatureDescriptor:
    """温度描述符 - 演示描述符协议"""
    
    def __init__(self, min_temp: float = -50.0, max_temp: float = 50.0):
        self.min_temp = min_temp
        self.max_temp = max_temp
        self.name = None
    
    def __set_name__(self, owner, name):
        self.name = f'_{name}'
    
    def __get__(self, instance, owner):
        if instance is None:
            return self
        return getattr(instance, self.name, 0.0)
    
    def __set__(self, instance, value):
        if not isinstance(value, (int, float)):
            raise TypeError("温度必须是数字")
        if not self.min_temp <= value <= self.max_temp:
            raise ValueError(f"温度必须在 {self.min_temp}°C 到 {self.max_temp}°C 之间")
        setattr(instance, self.name, float(value))

@total_ordering
class Animal(ABC):
    """抽象动物基类 - 演示抽象基类和比较操作"""
    
    # 类变量
    _instances: ClassVar[WeakSet] = WeakSet()
    _id_counter: ClassVar[int] = 0
    _lock: ClassVar[threading.Lock] = threading.Lock()
    
    # 描述符
    temperature = TemperatureDescriptor()
    
    def __init__(self, info: AnimalInfo):
        with self._lock:
            Animal._id_counter += 1
            self._id = Animal._id_counter
        
        self._info = info
        self._energy = 100.0
        self._is_sleeping = False
        
        # 注册实例
        Animal._instances.add(self)
        
        logger.info(f"创建动物: {self._info.name} (ID: {self._id})")
    
    @property
    def info(self) -> AnimalInfo:
        """获取动物信息"""
        return self._info
    
    @property
    def energy(self) -> float:
        """获取能量值"""
        return self._energy
    
    @energy.setter
    def energy(self, value: float) -> None:
        """设置能量值"""
        if not 0 <= value <= 100:
            raise ValueError("能量值必须在0-100之间")
        self._energy = value
    
    @property
    def is_sleeping(self) -> bool:
        """是否在睡觉"""
        return self._is_sleeping
    
    @abstractmethod
    def make_sound(self) -> str:
        """发出声音 - 抽象方法"""
        pass
    
    @abstractmethod
    def move(self) -> str:
        """移动方式 - 抽象方法"""
        pass
    
    def sleep(self) -> None:
        """睡觉"""
        self._is_sleeping = True
        self._energy = min(100.0, self._energy + 20.0)
        logger.info(f"{self._info.name} 开始睡觉，能量恢复到 {self._energy}")
    
    def wake_up(self) -> None:
        """醒来"""
        self._is_sleeping = False
        logger.info(f"{self._info.name} 醒来了")
    
    def validate(self) -> bool:
        """验证动物状态"""
        return (
            self._info.age >= 0 and
            0 <= self._energy <= 100 and
            self._info.weight >= 0
        )
    
    # 魔术方法
    def __str__(self) -> str:
        return f"{self._info.name} ({self._info.breed}, {self._info.age}岁)"
    
    def __repr__(self) -> str:
        return f"{self.__class__.__name__}(info={self._info!r})"
    
    def __eq__(self, other) -> bool:
        if not isinstance(other, Animal):
            return NotImplemented
        return self._id == other._id
    
    def __lt__(self, other) -> bool:
        if not isinstance(other, Animal):
            return NotImplemented
        return self._info.age < other._info.age
    
    def __hash__(self) -> int:
        return hash(self._id)
    
    def __enter__(self):
        """上下文管理器入口"""
        logger.info(f"开始照顾 {self._info.name}")
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口"""
        if exc_type is None:
            logger.info(f"完成照顾 {self._info.name}")
        else:
            logger.error(f"照顾 {self._info.name} 时发生错误: {exc_val}")
        return False
    
    @classmethod
    def get_instance_count(cls) -> int:
        """获取实例数量"""
        return len(cls._instances)
    
    @classmethod
    def get_all_instances(cls) -> List['Animal']:
        """获取所有实例"""
        return list(cls._instances)

class Dog(Animal):
    """狗类 - 继承自Animal"""
    
    def __init__(self, info: AnimalInfo, is_trained: bool = False):
        super().__init__(info)
        self._is_trained = is_trained
        self._tricks: List[str] = []
    
    @property
    def is_trained(self) -> bool:
        return self._is_trained
    
    @property
    def tricks(self) -> List[str]:
        return self._tricks.copy()
    
    def make_sound(self) -> str:
        """狗的叫声"""
        sound = "Woof! Woof!"
        if self._is_sleeping:
            sound = "Zzz... (睡觉中)"
        elif self._energy < 30:
            sound = "呜呜... (疲惫)"
        return sound
    
    def move(self) -> str:
        """狗的移动方式"""
        if self._is_sleeping:
            return "在睡觉，不能移动"
        elif self._energy < 20:
            return "慢慢走"
        else:
            return "快乐地跑步"
    
    def learn_trick(self, trick: str) -> bool:
        """学习新技能"""
        if not self._is_trained:
            logger.warning(f"{self._info.name} 还没有接受训练，无法学习技能")
            return False
        
        if trick not in self._tricks:
            self._tricks.append(trick)
            logger.info(f"{self._info.name} 学会了新技能: {trick}")
            return True
        return False
    
    def perform_trick(self, trick: str) -> str:
        """表演技能"""
        if trick in self._tricks:
            self._energy = max(0, self._energy - 10)
            return f"{self._info.name} 表演了 {trick}!"
        else:
            return f"{self._info.name} 不会 {trick}"

class Cat(Animal):
    """猫类 - 继承自Animal"""
    
    def __init__(self, info: AnimalInfo, indoor_only: bool = True):
        super().__init__(info)
        self._indoor_only = indoor_only
        self._hunting_score = 0
    
    @property
    def indoor_only(self) -> bool:
        return self._indoor_only
    
    @property
    def hunting_score(self) -> int:
        return self._hunting_score
    
    def make_sound(self) -> str:
        """猫的叫声"""
        if self._is_sleeping:
            return "呼噜呼噜... (睡觉中)"
        elif self._energy > 80:
            return "喵~ (兴奋)"
        else:
            return "喵..."
    
    def move(self) -> str:
        """猫的移动方式"""
        if self._is_sleeping:
            return "蜷缩着睡觉"
        else:
            return "优雅地踱步"
    
    def hunt(self) -> str:
        """狩猎"""
        if self._indoor_only:
            return f"{self._info.name} 是室内猫，不能狩猎"
        
        if self._energy < 30:
            return f"{self._info.name} 太累了，无法狩猎"
        
        self._energy -= 20
        self._hunting_score += 1
        return f"{self._info.name} 成功狩猎! 狩猎得分: {self._hunting_score}"

class AnimalFactory:
    """动物工厂 - 演示工厂模式"""
    
    _animal_types = {
        AnimalType.DOG: Dog,
        AnimalType.CAT: Cat,
    }
    
    @classmethod
    def create_animal(cls, animal_type: AnimalType, info: AnimalInfo, **kwargs) -> Animal:
        """创建动物实例"""
        if animal_type not in cls._animal_types:
            raise ValueError(f"不支持的动物类型: {animal_type}")
        
        animal_class = cls._animal_types[animal_type]
        return animal_class(info, **kwargs)
    
    @classmethod
    def register_animal_type(cls, animal_type: AnimalType, animal_class: type) -> None:
        """注册新的动物类型"""
        if not issubclass(animal_class, Animal):
            raise TypeError("动物类必须继承自Animal")
        cls._animal_types[animal_type] = animal_class

class Singleton:
    """单例模式基类"""
    _instances = {}
    _lock = threading.Lock()
    
    def __new__(cls, *args, **kwargs):
        if cls not in cls._instances:
            with cls._lock:
                if cls not in cls._instances:
                    cls._instances[cls] = super().__new__(cls)
        return cls._instances[cls]

class AnimalShelter(Singleton):
    """动物收容所 - 演示单例模式"""
    
    def __init__(self):
        if not hasattr(self, '_initialized'):
            self._animals: List[Animal] = []
            self._capacity = 50
            self._initialized = True
            logger.info("动物收容所已初始化")
    
    def add_animal(self, animal: Animal) -> bool:
        """添加动物"""
        if len(self._animals) >= self._capacity:
            logger.warning("收容所已满，无法添加更多动物")
            return False
        
        self._animals.append(animal)
        logger.info(f"动物 {animal.info.name} 已加入收容所")
        return True
    
    def remove_animal(self, animal: Animal) -> bool:
        """移除动物"""
        if animal in self._animals:
            self._animals.remove(animal)
            logger.info(f"动物 {animal.info.name} 已离开收容所")
            return True
        return False
    
    def get_animals_by_type(self, animal_type: type) -> List[Animal]:
        """按类型获取动物"""
        return [animal for animal in self._animals if isinstance(animal, animal_type)]
    
    @property
    def animal_count(self) -> int:
        return len(self._animals)
    
    @property
    def available_space(self) -> int:
        return self._capacity - len(self._animals)

def demonstrate_basic_classes() -> None:
    """演示基础类功能"""
    print("\n======== 1. 基础类和数据类 ========")
    
    # 创建动物信息
    dog_info = AnimalInfo(
        name="Buddy",
        age=3,
        breed="Golden Retriever",
        weight=30.5,
        vaccinated=True,
        tags=["friendly", "energetic"]
    )
    
    cat_info = AnimalInfo(
        name="Whiskers",
        age=2,
        breed="Persian",
        weight=4.2,
        vaccinated=True,
        tags=["calm", "indoor"]
    )
    
    print(f"✓ 狗信息: {dog_info}")
    print(f"✓ 猫信息: {cat_info}")

def demonstrate_inheritance_and_polymorphism() -> None:
    """演示继承和多态"""
    print("\n======== 2. 继承和多态 ========")
    
    # 使用工厂创建动物
    dog_info = AnimalInfo("Max", 4, "Labrador", 25.0, True)
    cat_info = AnimalInfo("Luna", 1, "Siamese", 3.5, True)
    
    dog = AnimalFactory.create_animal(AnimalType.DOG, dog_info, is_trained=True)
    cat = AnimalFactory.create_animal(AnimalType.CAT, cat_info, indoor_only=True)
    
    # 多态演示
    animals = [dog, cat]
    for animal in animals:
        print(f"✓ {animal}: {animal.make_sound()}")
        print(f"  移动方式: {animal.move()}")
        print(f"  验证状态: {animal.validate()}")
    
    # 狗的特殊功能
    dog.learn_trick("坐下")
    dog.learn_trick("握手")
    print(f"✓ {dog.perform_trick('坐下')}")
    
    # 比较操作
    print(f"✓ 年龄比较: {dog.info.name} {'比' if dog > cat else '不比'} {cat.info.name} 年龄大")

def demonstrate_descriptors_and_properties() -> None:
    """演示描述符和属性"""
    print("\n======== 3. 描述符和属性 ========")
    
    dog_info = AnimalInfo("Rex", 5, "German Shepherd", 35.0)
    dog = AnimalFactory.create_animal(AnimalType.DOG, dog_info)
    
    # 测试描述符
    try:
        dog.temperature = 38.5
        print(f"✓ 设置体温: {dog.temperature}°C")
        
        dog.temperature = 100  # 这会引发异常
    except ValueError as e:
        print(f"✓ 温度验证: {e}")
    
    # 测试属性
    try:
        dog.energy = 80
        print(f"✓ 设置能量: {dog.energy}")
        
        dog.energy = 150  # 这会引发异常
    except ValueError as e:
        print(f"✓ 能量验证: {e}")

def demonstrate_context_managers() -> None:
    """演示上下文管理器"""
    print("\n======== 4. 上下文管理器 ========")
    
    dog_info = AnimalInfo("Charlie", 2, "Beagle", 15.0)
    
    # 使用上下文管理器
    with AnimalFactory.create_animal(AnimalType.DOG, dog_info) as dog:
        print(f"✓ 正在照顾: {dog}")
        dog.sleep()
        dog.wake_up()

def demonstrate_singleton_pattern() -> None:
    """演示单例模式"""
    print("\n======== 5. 单例模式 ========")
    
    # 创建收容所实例
    shelter1 = AnimalShelter()
    shelter2 = AnimalShelter()
    
    print(f"✓ 单例验证: {shelter1 is shelter2}")
    
    # 添加动物到收容所
    dog_info = AnimalInfo("Shelter Dog", 3, "Mixed", 20.0)
    dog = AnimalFactory.create_animal(AnimalType.DOG, dog_info)
    
    shelter1.add_animal(dog)
    print(f"✓ 收容所动物数量: {shelter2.animal_count}")

def run_comprehensive_tests() -> None:
    """运行综合测试套件"""
    print("\n======== 6. 综合测试套件 ========")
    
    test_functions = [
        ("基础类测试", demonstrate_basic_classes),
        ("继承多态测试", demonstrate_inheritance_and_polymorphism),
        ("描述符属性测试", demonstrate_descriptors_and_properties),
        ("上下文管理器测试", demonstrate_context_managers),
        ("单例模式测试", demonstrate_singleton_pattern),
    ]
    
    passed = 0
    total = len(test_functions)
    
    for test_name, test_func in test_functions:
        try:
            test_func()
            print(f"✓ {test_name} 通过")
            passed += 1
        except Exception as e:
            print(f"✗ {test_name} 失败: {e}")
            logger.exception(f"测试失败: {test_name}")
    
    print(f"\n测试结果: {passed}/{total} 通过")
    print(f"总实例数: {Animal.get_instance_count()}")
    print("所有企业级类和对象最佳实践演示完成!")

if __name__ == "__main__":
    run_comprehensive_tests()